const vscode = require("vscode");
const path = require("path");
const util = require("../util.js");
const beforef = require("./before.js");
const afterf = require("./after.js");




async function getHtmlContent(uri) {
  const fs = vscode.workspace.fs;
  //   console.log(uri);
  return fs.readFile(uri).then((content) => {
    // console.log(content.toString());

    return content.toString();
  });
}
const pageMap = {};

const before_system = { 'name': '前置方法说明', 'content': beforef.show(), 'id': 'before_inner', 'status': true, 'edit': false }
const after_system = { 'name': '后置方法说明', 'content': afterf.show(), 'id': 'after_inner', 'status': true, 'edit': false }


async function getItemInfo(ctx, tid) {

  const items = JSON.parse(ctx.globalState.get(tid));
  const userMap = JSON.parse(ctx.globalState.get('user_userMap'))
  const users = []
  for (var i = 0; i < items.users.length; i++) {
    const u = userMap[items.users[i]]
    if (u?.name) {
      users.push(u.name)
    }
  }
  const before = [before_system]
  for (i = 0; i < items.before.length; i++) {
    const b = items.before[i]
    const st = b.status
    const da = JSON.parse(ctx.globalState.get(b.id))
    if (da.it != tid && !da.status) {
      continue
    }
    da.status = da.status && st;
    const item = JSON.parse(ctx.globalState.get(da.it))
    if (da.it != tid) {
      da.name = item.name + ' 的前置脚本'
      da.edit = false
    } else {
      da.name = "当前项目的前置脚本"
      da.edit = true
    }
    if (da.content !== '//请使用 js 语法\n') {
      // console.log('content2',da.content)
      const zda = await util.decompressBase64String(da.content)
      da.content = zda;
    }
    before.push({ ...da })
  }
  const after = [after_system]
  for (i = 0; i < items.after.length; i++) {
    const b = items.after[i]
    const st = b.status
    const da = JSON.parse(ctx.globalState.get(b.id))
    if (da.it != tid && !da.status) {
      continue
    }
    da.status = da.status && st
    const item = JSON.parse(ctx.globalState.get(da.it))
    if (da.it != tid) {
      da.name = item.name + ' 的后置脚本'
      da.edit = false
    } else {
      da.name = "当前项目的后置脚本"
      da.edit = true
    }
    if (da.content !== '//请使用 js 语法\n') {
      const zda = await util.decompressBase64String(da.content)
      da.content = zda;
    }
    after.push({ ...da })
  }
  return da = {
    id: tid,
    name: items.name,
    users: users.join(','),
    before: before,
    after: after,
    global: items.global,
    env: items.env
  }
}

function changeItem(ctx, da) {
  const items = JSON.parse(ctx.globalState.get(da.idd));
  let userInfo = ctx.globalState.get("user_userinfo");
  if (userInfo) {
    userInfo = JSON.parse(userInfo)
  } else {
    vscode.window.showErrorMessage('请先在左下角登录～')
    return
  }
  const users = da.users.split(',')
  if (users.indexOf(userInfo.name) == -1) {
    vscode.window.showErrorMessage('项目用户无法删除自己')
    return
  }
  let u = []
  for (var i = 0; i < users.length; i++) {
    const name = users[i].trim()
    if (!name || name == '') {
      continue
    }
    let localName = ctx.globalState.get(name);
    if (localName) {
      localName = JSON.parse(localName)
      u.push(localName.id)
    } else {
      let idd = util.getID("user");
      let daa = { name: name, id: idd, accessval: null };
      const userMap = JSON.parse(ctx.globalState.get('user_userMap'));
      userMap[idd] = daa;
      ctx.globalState.update(idd, JSON.stringify(daa));
      ctx.globalState.update('user_userMap', JSON.stringify(userMap))
      u.push(idd)
    }
  }
  items.name = da.name
  items.users = u
  ctx.globalState.update(da.idd, JSON.stringify(items));
  vscode.commands.executeCommand("daodan.refreshItem")
  panel.title=da.name
}
function delItem(ctx, da, panel) {
  const items = JSON.parse(ctx.globalState.get(da.idd));
  // console.log('pp',items.parent)
  if (items.parent) {
    const itemsP = JSON.parse(ctx.globalState.get(items.parent));
    let newC = []
    for (let i = 0; i < itemsP?.children.length; i++) {
      if (itemsP.children[i] == da.idd) {
        continue
      }
      newC.push(itemsP.children[i])
    }
    itemsP.children = newC
    ctx.globalState.update(itemsP.id, JSON.stringify(itemsP))
  } else {
    const list = JSON.parse(ctx.globalState.get("daodan.itemList"));
    let listt = []
    for (var x = 0; x < list.length; x++) {
      if (list[x] == da.idd) {
        continue
      }
      listt.push(list[x])
    }
    ctx.globalState.update("daodan.itemList", JSON.stringify(listt))
  }
  for (var i = 0; i < items.before; i++) {
    if(items.before[i]?.it==items.id){
      ctx.globalState.update(items.before[i].id, null)
      ctx.globalState.update(items.before[i].id+"_file", null)
      break;
    }
  }

  for (var i = 0; i < items.after; i++) {
    if(items.after[i]?.id==items.id){
      ctx.globalState.update(items.after[i].id, null)
      ctx.globalState.update(items.after[i].id+"_file", null)
      break;
    }
  }
  JSON.parse(ctx.globalState.get('daodan.apiList')).forEach((aid)=>{
    const api=JSON.parse(ctx.globalState.get(aid)?ctx.globalState.get(aid):'{}')
    if(api.itemid==da.idd){
      removeApi(ctx,a.id)
    }
  })
  ctx.globalState.update(da.idd, null)
  panel.dispose();
  // panel.webview.postMessage({ command: "closeWindow" });
  // vscode.window.showInformationMessage('删除成功！');
  vscode.commands.executeCommand("daodan.refreshItem");

}
function removeApi(ctx,aid){
  const api=JSON.parse(ctx.globalState.get(aid))
  const apilist=JSON.parse(ctx.globalState.get('daodan.apiList'))
  if(apilist.indexOf(aid)!=-1){
    const newlist=[]
    for(var i=0;i<apilist.length;i++){
      if(apilist[i]==aid){
        continue
      }
      newlist.push(apilist[i])
    }
    ctx.globalState.update('daodan.apiList',JSON.stringify(newlist))
  }
  for (var i = 0; i < api.before; i++) {
    if(api.before[i]?.aid==aid){
      ctx.globalState.update(api.before[i].id, null)
      ctx.globalState.update(api.before[i].id+"_file", null)
      break;
    }
  }

  for (var i = 0; i < api.after; i++) {
    if(api.after[i]?.aid==aid){
      ctx.globalState.update(api.after[i].id, null)
      ctx.globalState.update(api.after[i].id+"_file", null)
      break;
    }
  }
  ctx.globalState.update(aid, null)
}
function sendGlobalStateInit(ctx) {
  let v = ctx.globalState.keys();
  const da = { 'all': 'all' }
  for (var i in v) {
    const vv = ctx.globalState.get(v[i]);
    if (!vv || vv.indexOf('accessval') != -1) {
      continue
    }
    da[v[i]] = vv
  }
  // console.log('dddd',da)
  return da;

}
function setStatus4ab(ctx, da) {
  console.log(da)
  const da2 = JSON.parse(ctx.globalState.get(da.id))
  da2.status = da.status;
  ctx.globalState.update(da.id, JSON.stringify(da2))
  const item = JSON.parse(ctx.globalState.get(da.tid))
  if (!item) {
    vscode.window.showWarningMessage('信息异常，请重新打开')
    return
  }
  const p = item[da.position]
  for (var i = 0; i < p.length; i++) {
    if (p[i].id == da.id) {
      item[da.position][i].status = da.status;
      ctx.globalState.update(da.tid, JSON.stringify(item))
      break
    }
  }
}
function setStatus4env(ctx, da) {
  const item = JSON.parse(ctx.globalState.get(da.tid))
  if (!item) {
    vscode.window.showWarningMessage('项目信息异常，请重新打开项目')
    return
  }
  item.env[da.id].status = da.status;
  ctx.globalState.update(da.tid, JSON.stringify(item));
}
function setSelect4env(ctx, da) {
  const item = JSON.parse(ctx.globalState.get(da.tid))
  if (!item) {
    vscode.window.showWarningMessage('项目信息异常，请重新打开项目~')
    return
  }
  item.env[da.old].selected = false;
  item.env[da.now].selected = true;
  ctx.globalState.update(da.tid, JSON.stringify(item));
}
function openTmpFile(da) {
  vscode.commands.executeCommand('daodan.openTmpFile', da);
}
function saveUrl(ctx, da) {
  const item = JSON.parse(ctx.globalState.get(da.itemID))
  if (!item) {
    vscode.window.showWarningMessage('项目信息异常，请重新打开项目')
    return
  }
  item.env[da.env].url = da.url;
  ctx.globalState.update(da.itemID, JSON.stringify(item));
  vscode.window.showInformationMessage("操作成功");
}
function updateTable(ctx, da) {
  const item = JSON.parse(ctx.globalState.get(da.itemID))
  if (!item) {
    vscode.window.showWarningMessage('项目信息异常，请重新打开项目')
    return
  }
  if (da.position == 'paramsTable') {
    if (da.del) {
      delete item.global.params[da.key]
    } else {
      item.global.params[da.key] = { key: da.key, value: da.val, remark: da.remark }
    }
  } else if (da.position.endsWith('_id')) {
    if (da.del) {
      delete item.env[da.position.replace('_id', '')].params[da.key]
    } else {
      item.env[da.position.replace('_id', '')].params[da.key] = { key: da.key, value: da.val, remark: da.remark }
    }
  }
  ctx.globalState.update(da.itemID, JSON.stringify(item))
  vscode.window.showInformationMessage("操作成功")

}

async function getApiInfo(ctx, tid, aid) {
  const inter = JSON.parse(ctx.globalState.get(aid));
  if (!inter) {
    vscode.window.showWarningMessage('接口信息异常，请重新打开接口')
    return null;
  }
  //   const items = JSON.parse(ctx.globalState.get(tid));
  // if(!items){
  //   vscode.window.showWarningMessage('接口信息异常，请重新打开接口~')
  //     return null;
  // }
  const before = [before_system]
  for (i = 0; i < inter.before.length; i++) {
    const b = inter.before[i]
    const st = b.status
    const da = JSON.parse(ctx.globalState.get(b.id))
    if (da.it != tid && !da.status) {
      continue
    }

    const item = JSON.parse(ctx.globalState.get(da.it))
    if (da.it != tid) {
      da.name = item.name + ' 的前置脚本'
      da.edit = false
    } else {
      if (da.aid && da.aid == aid) {
        da.name = "当前接口的前置脚本"
        da.edit = true
      } else {
        if (!da.status) {
          continue
        }
        da.name = "当前项目的前置脚本"
        da.edit = false
      }
    }
    da.status = da.status && st;
    if (da.content !== '//请使用 js 语法\n') {
      const zda = await util.decompressBase64String(da.content)
      da.content = zda;
    }
    before.push({ ...da })
  }
  inter.apiInfo.before = [...before]
  const after = [after_system]
  for (i = 0; i < inter.after.length; i++) {
    const b = inter.after[i]
    const st = b.status
    const da = JSON.parse(ctx.globalState.get(b.id))
    if (da.it != tid && !da.status) {
      continue
    }

    const item = JSON.parse(ctx.globalState.get(da.it))
    if (da.it != tid) {
      da.name = item.name + ' 的后置脚本'
      da.edit = false
    } else {
      if (da.aid && da.aid == aid) {
        da.name = "当前接口的后置脚本"
        da.edit = true
      } else {
        if (!da.status) {
          continue
        }
        da.name = "当前项目的后置脚本"
        da.edit = false
      }
    }
    da.status = da.status && st
    if (da.content !== '//请使用 js 语法\n') {
      const zda = await util.decompressBase64String(da.content)
      da.content = zda;
    }
    after.push({ ...da })
  }
  inter.apiInfo.after = [...after]
  return inter

}
function setApiInfo(ctx, da, id) {
  // console.log('api', da, id)
  const api = JSON.parse(ctx.globalState.get(id))
  delete da.before
  delete da.after
  api.apiInfo = { ...da }

  ctx.globalState.update(id, JSON.stringify(api))
}
function setGlobalInfo(ctx, da, id){
  const item = JSON.parse(ctx.globalState.get(id))
  item.global.req={...da}
  ctx.globalState.update(id, JSON.stringify(item))
}
async function sendapi(da,panel) {
  // let tid = da.tid
  console.log('sendapi',da)
  const redata={request:da,response:{},error:null,startTime:Date.now()}
  try {
    const d = await util.request(da.method, da.url, da.params, da.body, da.headers, da.timeout)
    const endTime = Date.now(); 
    console.log('ddd', d)
    redata.request.url=d.request.protocol+'//'+d.request.host+d.request.path
    Object.keys(d.config.headers).forEach(key=>{
      redata.request.headers[key]=d.config.headers[key]
    })
    redata.response.status=d.status
    redata.response.statusText=d.statusText
    redata.response.headers={...d.headers}
    redata.response.data=d.data
    redata.response.cost=endTime-redata.startTime
  } catch (e) {
    redata.error=e.message
  }
  panel.webview.postMessage({ command: "sendresult", da: redata });

}
function saveApiInfo(ctx, da,panel){
  const api = JSON.parse(ctx.globalState.get(da.id))
  api.name=da.name
  ctx.globalState.update(da.id, JSON.stringify(api))
  vscode.commands.executeCommand("daodan.refreshInterface");
  panel.title=da.name
  
}
function delApi(ctx, da, panel) {
  removeApi(ctx, da.id)
  panel.dispose();
  vscode.commands.executeCommand("daodan.refreshInterface");
}
function runScript(panel, da) {
  const res=util.run(da.params,da.req,da.res,da.code);
  console.log('runScript',res);
  if(res.stop.flag){
    res.error='脚本执行中断:'+res.stop.reason
  }
  panel.webview.postMessage({ command: "runScriptResult", da: res });
  if(res.error){
    return
  }
  sendapi(res.request,panel);
  
}



class web {
  constructor() {
    this.ctx = null;
  }
  setctx(ctx) {
    this.ctx = ctx;
    this.init();
  }

  init() {
    let openweb = vscode.commands.registerCommand(
      "daodan.openWeb",
      (params) => {
        console.log(222, params);
        const p = pageMap[params.id];
        if (p) {
          p.reveal(vscode.ViewColumn.One);
        } else {
          let panel = vscode.window.createWebviewPanel(
            params.title,
            params.label,
            vscode.ViewColumn.One,
            { enableScripts: true }
          );
          let htmlpath = vscode.Uri.file(
            path.join(this.ctx.extensionPath, "html", "item_index.html")
          );
          if (params.type == 'dir') {
            htmlpath = vscode.Uri.file(
              path.join(this.ctx.extensionPath, "html", "item_dir_index.html")
            );
          } else if (params.type == 'globalState') {
            htmlpath = vscode.Uri.file(
              path.join(this.ctx.extensionPath, "html", "globalState_index.html")
            );
          } else if (params.type == 'api') {
            htmlpath = vscode.Uri.file(
              path.join(this.ctx.extensionPath, "html", "api_index.html")
            );
          }
          getHtmlContent(htmlpath).then((res) => {
            panel.webview.html = res;
          });
          panel.webview.onDidReceiveMessage((message) => {
            // console.log("mafg", message);
            if (message.command === "showMessage") {
              vscode.window.showInformationMessage(message.text);
            } else if (message.command === "itemInit") {
              getItemInfo(this.ctx, params.tid).then((res) => {
                panel.webview.postMessage({ command: "itemInfo", da: res });
              })
            } else if (message.command === "message") {
              vscode.window.showInformationMessage(message.content);
            } else if (message.command === "changeItem") {
              changeItem(this.ctx, message.da,panel);
            } else if (message.command === "delItem") {
              delItem(this.ctx, message.da, panel);
            } else if (message.command === 'globalStateInit') {
              panel.webview.postMessage({ command: "globalStateInit", da: sendGlobalStateInit(this.ctx) });
            } else if (message.command === 'globalStateDel') {
              if (message.da.id == 'all') {
                let v = this.ctx.globalState.keys();
                for (var i in v) {
                  this.ctx.globalState.update(v[i], null);
                }
              } else {
                this.ctx.globalState.update(message.da.id);
              }
              panel.webview.postMessage({ command: "globalStateRefresh", da: sendGlobalStateInit(this.ctx) });
            } else if (message.command === 'setStatus4ab') {
              setStatus4ab(this.ctx, message.da);
            } else if (message.command === 'openTmpFile') {
              openTmpFile(message.da);
            } else if (message.command === 'setStatus4env') {
              setStatus4env(this.ctx, message.da);
            } else if (message.command === 'setSelect4env') {
              setSelect4env(this.ctx, message.da);
            } 
            else if (message.command === 'updateTable') {
              updateTable(this.ctx, message.da)
            } else if (message.command === 'saveUrl') {
              saveUrl(this.ctx, message.da)
            } else if (message.command === 'apiInit') {
              getApiInfo(this.ctx, params.tid, params.aid).then((res) => {
                panel.webview.postMessage({ command: "apiInfo", da: res });
              })
            } else if (message.command === 'sendapi') {
              sendapi(message.da,panel)
            } else if (message.command === 'setApiInfo') {
              setApiInfo(this.ctx, message.da, message.aid);
            }else if('setGlobalInfo'===message.command){
              setGlobalInfo(this.ctx, message.da, message.tid);
            }else if('runScript'===message.command){
              runScript(panel, message.da);
            }else if('saveApiInfo'===message.command){
              saveApiInfo(this.ctx, message.da,panel);
            }else if('delApi'===message.command){
              delApi(this.ctx, message.da, panel);
            }else if('exportApi'===message.command){
              exportApi(message.da)
            }
          });
          panel.webview.postMessage({ command: "initialize2" });
          panel.onDidDispose(() => {
            panel = null;
            pageMap[params.id] = panel;
          });
          pageMap[params.id] = panel;
        }
      }
    );
    this.ctx.subscriptions.push(openweb);
  }
}

module.exports = {
  web
};
